﻿using System;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using Miris.HumanMilkAnalyser.DataModel;
using Miris.HumanMilkAnalyser.Service.Interface;
using Miris.HumanMilkAnalyser.Service.Shared;
using Miris.HumanMilkAnalyser.Service.Validation;
using Miris.HumanMilkAnalyser.WPF.Model;
using Miris.HumanMilkAnalyser.WPF.Shared;

namespace Miris.HumanMilkAnalyser.WPF.ViewModel
{
    public class PatientViewModel : MyViewModelBase
    {
        public const string UpdatePatientDataMessageToken = "PatientUpdatePatientDataMessage";
        protected IPatientService PatientService;

        /// <summary>
        /// Initializes a new instance of the PatientViewModel class.
        /// </summary>
        public PatientViewModel(IDataService dataService)
            : base(dataService)
        {
            PatientService = ServiceFactory.CreatePatientService();
        }

        /// <summary>
        /// Set all patient properties based on provided patient number.
        /// </summary>
        /// <param name="patientNumber">The provided patient number.</param>
        public virtual void SetPatientProperties(string patientNumber)
        {
            var patient = PatientService.Get(patientNumber);
            SetPatientProperties(patient);
        }

        /// <summary>
        /// Set all patient properties based on provided patient.
        /// </summary>
        /// <param name="patientNumber">The provided patient number.</param>
        public virtual void SetPatientProperties(Patient patient)
        {
            Number = patient.Number;
            MotherName = patient.MotherName;
            MotherAge = patient.MotherAge;
            MotherHeight = patient.MotherHeight;
            MotherWeight = patient.MotherWeight;
            MotherBMI = patient.MotherBMI;
            MotherDeliveryMode = patient.MotherDeliveryMode;
            MotherOpenMilkDate = patient.MotherOpenMilkDate;
            MotherOpenMilkDateDisplay = patient.MotherOpenMilkDate.ToString(GeneralUtility.ShortDateFormat);
            MotherEmotion = patient.MotherEmotion;
            MotherBadHabit = patient.MotherBadHabit;

            BabyName = patient.BabyName;
            BabyBirthday = patient.BabyBirthday;
            BabyBirthdayDisplay = patient.BabyBirthday.ToString(GeneralUtility.ShortDateFormat);
            IsGirl = patient.BabyGender == (short)GeneralUtility.Gender.Female ? true : false;
            BabyGenderDisplay = IsGirl ? "女" : "男";
            IsBabyNotPrematureDelivery = !patient.IsBabyPrematureDelivery;
            IsBabyPrematureDeliveryDisplay = IsBabyNotPrematureDelivery ? "否" : "是";
            BabyHeight = patient.BabyHeight;
            BabyWeight = patient.BabyWeight;
            BabyHeadCircumference = patient.BabyHeadCircumference;
            BabyBirthHeight = patient.BabyBirthHeight;
            BabyBirthWeight = patient.BabyBirthWeight;
            BabyBirthHeadCircumference = patient.BabyBirthHeadCircumference;
            Apgar = patient.Apgar;

            IsNewData = false;
        }

        /// <summary>
        /// Set all patient properties based on provided class instance of PatientViewModel.
        /// </summary>
        /// <param name="patientViewModel">The provided patient number.</param>
        public virtual void SetPatientProperties(PatientViewModel patient)
        {
            Number = patient.Number;
            MotherName = patient.MotherName;
            MotherAge = patient.MotherAge;
            MotherHeight = patient.MotherHeight;
            MotherWeight = patient.MotherWeight;
            MotherBMI = patient.MotherBMI;
            MotherDeliveryMode = patient.MotherDeliveryMode;
            MotherOpenMilkDate = patient.MotherOpenMilkDate;
            MotherOpenMilkDateDisplay = patient.MotherOpenMilkDateDisplay;
            MotherEmotion = patient.MotherEmotion;
            MotherBadHabit = patient.MotherBadHabit;

            BabyName = patient.BabyName;
            BabyBirthday = patient.BabyBirthday;
            BabyBirthdayDisplay = patient.BabyBirthdayDisplay;
            IsGirl = patient.IsGirl;
            BabyGenderDisplay = patient.BabyGenderDisplay;
            IsBabyPrematureDeliveryDisplay = patient.IsBabyPrematureDeliveryDisplay;
            IsBabyNotPrematureDelivery = patient.IsBabyNotPrematureDelivery;
            BabyHeight = patient.BabyHeight;
            BabyWeight = patient.BabyWeight;
            BabyHeadCircumference = patient.BabyHeadCircumference;
            BabyBirthHeight = patient.BabyBirthHeight;
            BabyBirthWeight = patient.BabyBirthWeight;
            BabyBirthHeadCircumference = patient.BabyBirthHeadCircumference;
            Apgar = patient.Apgar;

            IsNewData = false;
        }

        /// <summary>
        /// Create a instance of Patient based on current ViewModel properties values.
        /// </summary>
        /// <returns>A instance of Patient if data meets rules. Otherwise, NULL will be returned.</returns>
        protected virtual Patient CreatePatient()
        {
            return new Patient
            {
                Number = Number,
                MotherName = MotherName,
                MotherAge = MotherAge,
                MotherHeight = MotherHeight,
                MotherWeight = MotherWeight,
                MotherBMI = GeneralUtility.CalcuateBMI(MotherHeight, MotherWeight),
                MotherOpenMilkDate = MotherOpenMilkDate,
                MotherDeliveryMode = MotherDeliveryMode,
                MotherEmotion = MotherEmotion,
                MotherBadHabit = MotherBadHabit,
                BabyName = BabyName,
                BabyBirthday = BabyBirthday,
                BabyGender = IsGirl ? (short)GeneralUtility.Gender.Female : (short)GeneralUtility.Gender.Male,
                IsBabyPrematureDelivery = !IsBabyNotPrematureDelivery,
                BabyHeight = BabyHeight,
                BabyWeight = BabyWeight,
                BabyHeadCircumference = BabyHeadCircumference,
                BabyBirthHeight = BabyBirthHeight,
                BabyBirthWeight = BabyBirthWeight,
                BabyBirthHeadCircumference = BabyBirthHeadCircumference,
                Apgar = Apgar,
                CreateOn = GeneralUtility.GetCurrentDateTime(),
                UpdateOn = GeneralUtility.GetCurrentDateTime()
            };
        }

        /// <summary>
        /// Add a new patient or update existing patient into data source.
        /// </summary>
        /// <returns>True means Operaton complete successfully. False means failed.</returns>
        protected virtual bool AddOrUpdatePatient()
        {
            var patient = CreatePatient();

            // Adding new data
            if (IsNewData)
            {
                // Check the existed data.
                if (PatientService.Get(patient.Number) == null)
                {
                    PatientService.Add(patient);
                    SetPatientProperties(patient);
                }
                else
                {
                    RequestDisplayMessage(string.Format("编号{0}已存在", patient.Number));
                    return false;
                }
            }
            else
            {
                // Update existing data
                PatientService.Update(patient);
            }

            return true;
        }

        /// <summary>
        /// Check if patient data is valid to see If can execute current command.
        /// </summary>
        /// <returns>True means current command can be executed. False means NOT.</returns>
        protected virtual bool CanExecuteCommand()
        {
            var patient = CreatePatient();

            if (patient == null)
            {
                return false;
            }
            else
            {
                var patientValidator = new PatientValidator();
                patientValidator.Validate(patient);

                if (!patientValidator.IsValid)
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// Get the default date for baby birthday and mother open milk date.
        /// </summary>
        /// <returns></returns>
        protected virtual DateTime GetDefaultDate()
        {
            return GeneralUtility.GetCurrentDateTime().AddMonths(-6);
        }

        /// <summary>
        /// The <see cref="IsNewData" /> property's name.
        /// </summary>
        public const string IsNewDataPropertyName = "IsNewData";

        private bool _isNewData = true;

        /// <summary>
        /// Sets and gets the IsNewData property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public bool IsNewData
        {
            get
            {
                return _isNewData;
            }

            set
            {
                if (_isNewData == value)
                {
                    return;
                }

                RaisePropertyChanging(IsNewDataPropertyName);
                _isNewData = value;
                RaisePropertyChanged(IsNewDataPropertyName);
            }
        }
        
        /// <summary>
        /// The <see cref="SequenceNumber" /> property's name.
        /// </summary>
        public const string SequenceNumberPropertyName = "SequenceNumber";

        private int _sequenceNumber = 0;

        /// <summary>
        /// Sets and gets the SequenceNumber property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public int SequenceNumber
        {
            get
            {
                return _sequenceNumber;
            }

            set
            {
                if (_sequenceNumber == value)
                {
                    return;
                }

                RaisePropertyChanging(SequenceNumberPropertyName);
                _sequenceNumber = value;
                RaisePropertyChanged(SequenceNumberPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="Number" /> property's name.
        /// </summary>
        public const string NumberPropertyName = "Number";

        private string _number = string.Empty;

        /// <summary>
        /// Sets and gets the Number property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string Number
        {
            get
            {
                return _number;
            }

            set
            {
                if (_number == value)
                {
                    return;
                }

                RaisePropertyChanging(NumberPropertyName);
                _number = value;
                RaisePropertyChanged(NumberPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="MotherName" /> property's name.
        /// </summary>
        public const string MotherNamePropertyName = "MotherName";

        private string _motherName = string.Empty;

        /// <summary>
        /// Sets and gets the MotherName property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string MotherName
        {
            get
            {
                return _motherName;
            }

            set
            {
                if (_motherName == value)
                {
                    return;
                }

                RaisePropertyChanging(MotherNamePropertyName);
                _motherName = value;
                RaisePropertyChanged(MotherNamePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="MotherAge" /> property's name.
        /// </summary>
        public const string MotherAgePropertyName = "MotherAge";

        private short? _motherAge = null;

        /// <summary>
        /// Sets and gets the MotherAge property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public short? MotherAge
        {
            get
            {
                return _motherAge;
            }

            set
            {
                if (_motherAge == value)
                {
                    return;
                }

                RaisePropertyChanging(MotherAgePropertyName);
                _motherAge = value;
                RaisePropertyChanged(MotherAgePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="MotherHeight" /> property's name.
        /// </summary>
        public const string MotherHeightPropertyName = "MotherHeight";

        private double? _motherHeight = null;

        /// <summary>
        /// Sets and gets the MotherHeight property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public double? MotherHeight
        {
            get
            {
                return _motherHeight;
            }

            set
            {
                if (_motherHeight == value)
                {
                    return;
                }

                RaisePropertyChanging(MotherHeightPropertyName);
                _motherHeight = value;
                RaisePropertyChanged(MotherHeightPropertyName);

                CalcuateMotherBMI();
            }
        }

        /// <summary>
        /// The <see cref="MotherWeight" /> property's name.
        /// </summary>
        public const string MotherWeightPropertyName = "MotherWeight";

        private double? _motherWeight = null;

        /// <summary>
        /// Sets and gets the MotherWeight property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public double? MotherWeight
        {
            get
            {
                return _motherWeight;
            }

            set
            {
                if (_motherWeight == value)
                {
                    return;
                }

                RaisePropertyChanging(MotherWeightPropertyName);
                _motherWeight = value;
                RaisePropertyChanged(MotherWeightPropertyName);

                CalcuateMotherBMI();
            }
        }

        /// <summary>
        /// The <see cref="MotherBMI" /> property's name.
        /// </summary>
        public const string MotherBMIPropertyName = "MotherBMI";

        private double? _motherBMI = null;

        /// <summary>
        /// Sets and gets the MotherBMI property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public double? MotherBMI
        {
            get
            {
                return _motherBMI;
            }

            set
            {
                if (_motherBMI == value)
                {
                    return;
                }

                RaisePropertyChanging(MotherBMIPropertyName);
                _motherBMI = value;
                RaisePropertyChanged(MotherBMIPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="MotherOpenMilkDate" /> property's name.
        /// </summary>
        public const string MotherOpenMilkDatePropertyName = "MotherOpenMilkDate";

        private DateTime _motherOpenMilkDate;

        /// <summary>
        /// Sets and gets the MotherOpenMilkDate property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public DateTime MotherOpenMilkDate
        {
            get
            {
                return _motherOpenMilkDate;
            }

            set
            {
                if (_motherOpenMilkDate == value)
                {
                    return;
                }

                RaisePropertyChanging(MotherOpenMilkDatePropertyName);
                _motherOpenMilkDate = value;
                RaisePropertyChanged(MotherOpenMilkDatePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="MotherOpenMilkDateDisplay" /> property's name.
        /// </summary>
        public const string MotherOpenMilkDateDisplayPropertyName = "MotherOpenMilkDateDisplay";

        private string _motherOpenMilkDateDisplay = string.Empty;

        /// <summary>
        /// Sets and gets the MotherOpenMilkDateDisplay property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string MotherOpenMilkDateDisplay
        {
            get
            {
                return _motherOpenMilkDateDisplay;
            }

            set
            {
                if (_motherOpenMilkDateDisplay == value)
                {
                    return;
                }

                RaisePropertyChanging(MotherOpenMilkDateDisplayPropertyName);
                _motherOpenMilkDateDisplay = value;
                RaisePropertyChanged(MotherOpenMilkDateDisplayPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="MotherDeliveryMode" /> property's name.
        /// </summary>
        public const string MotherDeliveryModePropertyName = "MotherDeliveryMode";

        private string _motherDeliveryMode = string.Empty;

        /// <summary>
        /// Sets and gets the MotherDeliveryMode property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string MotherDeliveryMode
        {
            get
            {
                return _motherDeliveryMode;
            }

            set
            {
                if (_motherDeliveryMode == value)
                {
                    return;
                }

                RaisePropertyChanging(MotherDeliveryModePropertyName);
                _motherDeliveryMode = value;
                RaisePropertyChanged(MotherDeliveryModePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="MotherEmotion" /> property's name.
        /// </summary>
        public const string MotherEmotionPropertyName = "MotherEmotion";

        private string _motherEmotion = string.Empty;

        /// <summary>
        /// Sets and gets the MotherEmotion property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string MotherEmotion
        {
            get
            {
                return _motherEmotion;
            }

            set
            {
                if (_motherEmotion == value)
                {
                    return;
                }

                RaisePropertyChanging(MotherEmotionPropertyName);
                _motherEmotion = value;
                RaisePropertyChanged(MotherEmotionPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="MotherBadHabit" /> property's name.
        /// </summary>
        public const string MotherBadHabitPropertyName = "MotherBadHabit";

        private string _motherBadHabit = string.Empty;

        /// <summary>
        /// Sets and gets the MotherBadHabit property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string MotherBadHabit
        {
            get
            {
                return _motherBadHabit;
            }

            set
            {
                if (_motherBadHabit == value)
                {
                    return;
                }

                RaisePropertyChanging(MotherBadHabitPropertyName);
                _motherBadHabit = value;
                RaisePropertyChanged(MotherBadHabitPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="BabyName" /> property's name.
        /// </summary>
        public const string BabyNamePropertyName = "BabyName";

        private string _babyName = string.Empty;

        /// <summary>
        /// Sets and gets the BabyName property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string BabyName
        {
            get
            {
                return _babyName;
            }

            set
            {
                if (_babyName == value)
                {
                    return;
                }

                RaisePropertyChanging(BabyNamePropertyName);
                _babyName = value;
                RaisePropertyChanged(BabyNamePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="IsGirl" /> property's name.
        /// </summary>
        public const string IsGirlPropertyName = "IsGirl";

        private bool _isGirl = true;

        /// <summary>
        /// Sets and gets the IsGirl property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public bool IsGirl
        {
            get
            {
                return _isGirl;
            }

            set
            {
                if (_isGirl == value)
                {
                    return;
                }

                RaisePropertyChanging(IsGirlPropertyName);
                _isGirl = value;
                RaisePropertyChanged(IsGirlPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="BabyGenderDisplay" /> property's name.
        /// </summary>
        public const string BabyGenderDisplayPropertyName = "BabyGenderDisplay";

        private string _babyGenderDisplay = string.Empty;

        /// <summary>
        /// Sets and gets the BabyGenderDisplay property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string BabyGenderDisplay
        {
            get
            {
                return _babyGenderDisplay;
            }

            set
            {
                if (_babyGenderDisplay == value)
                {
                    return;
                }

                RaisePropertyChanging(BabyGenderDisplayPropertyName);
                _babyGenderDisplay = value;
                RaisePropertyChanged(BabyGenderDisplayPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="BabyBirthday" /> property's name.
        /// </summary>
        public const string BabyBirthdayPropertyName = "BabyBirthday";

        private DateTime _babyBirthday;

        /// <summary>
        /// Sets and gets the BabyBirthday property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public DateTime BabyBirthday
        {
            get
            {
                return _babyBirthday;
            }

            set
            {
                if (_babyBirthday == value)
                {
                    return;
                }

                RaisePropertyChanging(BabyBirthdayPropertyName);
                _babyBirthday = value;
                RaisePropertyChanged(BabyBirthdayPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="BabyBirthdayDisplay" /> property's name.
        /// </summary>
        public const string BabyBirthdayDisplayPropertyName = "BabyBirthdayDisplay";

        private string _babyBirthdayDisplay = string.Empty;

        /// <summary>
        /// Sets and gets the BabyBirthdayDisplay property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string BabyBirthdayDisplay
        {
            get
            {
                return _babyBirthdayDisplay;
            }

            set
            {
                if (_babyBirthdayDisplay == value)
                {
                    return;
                }

                RaisePropertyChanging(BabyBirthdayDisplayPropertyName);
                _babyBirthdayDisplay = value;
                RaisePropertyChanged(BabyBirthdayDisplayPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="IsBabyNotPrematureDelivery" /> property's name.
        /// </summary>
        public const string IsBabyNotPrematureDeliveryPropertyName = "IsBabyNotPrematureDelivery";

        private bool _isBabyNotPrematureDelivery = true;

        /// <summary>
        /// Sets and gets the IsBabyNotPrematureDelivery property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public bool IsBabyNotPrematureDelivery
        {
            get
            {
                return _isBabyNotPrematureDelivery;
            }

            set
            {
                if (_isBabyNotPrematureDelivery == value)
                {
                    return;
                }

                RaisePropertyChanging(IsBabyNotPrematureDeliveryPropertyName);
                _isBabyNotPrematureDelivery = value;
                RaisePropertyChanged(IsBabyNotPrematureDeliveryPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="IsBabyPrematureDeliveryDisplay" /> property's name.
        /// </summary>
        public const string IsBabyPrematureDeliveryDisplayPropertyName = "IsBabyPrematureDeliveryDisplay";

        private string _isBabyPrematureDeliveryDisplay = string.Empty;

        /// <summary>
        /// Sets and gets the IsBabyPrematureDeliveryDisplay property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string IsBabyPrematureDeliveryDisplay
        {
            get
            {
                return _isBabyPrematureDeliveryDisplay;
            }

            set
            {
                if (_isBabyPrematureDeliveryDisplay == value)
                {
                    return;
                }

                RaisePropertyChanging(IsBabyPrematureDeliveryDisplayPropertyName);
                _isBabyPrematureDeliveryDisplay = value;
                RaisePropertyChanged(IsBabyPrematureDeliveryDisplayPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="BabyHeight" /> property's name.
        /// </summary>
        public const string BabyHeightPropertyName = "BabyHeight";

        private double? _babyHeight = null;

        /// <summary>
        /// Sets and gets the BabyHeight property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public double? BabyHeight
        {
            get
            {
                return _babyHeight;
            }

            set
            {
                if (_babyHeight == value)
                {
                    return;
                }

                RaisePropertyChanging(BabyHeightPropertyName);
                _babyHeight = value;
                RaisePropertyChanged(BabyHeightPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="BabyWeight" /> property's name.
        /// </summary>
        public const string BabyWeightPropertyName = "BabyWeight";

        private double? _babyWeight = null;

        /// <summary>
        /// Sets and gets the BabyWeight property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public double? BabyWeight
        {
            get
            {
                return _babyWeight;
            }

            set
            {
                if (_babyWeight == value)
                {
                    return;
                }

                RaisePropertyChanging(BabyWeightPropertyName);
                _babyWeight = value;
                RaisePropertyChanged(BabyWeightPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="BabyHeadCircumference" /> property's name.
        /// </summary>
        public const string BabyHeadCircumferencePropertyName = "BabyHeadCircumference";

        private double? _babyHeadCircumference = null;

        /// <summary>
        /// Sets and gets the BabyHeadCircumference property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public double? BabyHeadCircumference
        {
            get
            {
                return _babyHeadCircumference;
            }

            set
            {
                if (_babyHeadCircumference == value)
                {
                    return;
                }

                RaisePropertyChanging(BabyHeadCircumferencePropertyName);
                _babyHeadCircumference = value;
                RaisePropertyChanged(BabyHeadCircumferencePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="BabyBirthHeight" /> property's name.
        /// </summary>
        public const string BabyBirthHeightPropertyName = "BabyBirthHeight";

        private double? _babyBirthHeight = null;

        /// <summary>
        /// Sets and gets the BabyBirthHeight property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public double? BabyBirthHeight
        {
            get
            {
                return _babyBirthHeight;
            }

            set
            {
                if (_babyBirthHeight == value)
                {
                    return;
                }

                RaisePropertyChanging(BabyBirthHeightPropertyName);
                _babyBirthHeight = value;
                RaisePropertyChanged(BabyBirthHeightPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="BabyBirthWeight" /> property's name.
        /// </summary>
        public const string BabyBirthWeightPropertyName = "BabyBirthWeight";

        private double? _babyBirthWeight = null;

        /// <summary>
        /// Sets and gets the BabyBirthWeight property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public double? BabyBirthWeight
        {
            get
            {
                return _babyBirthWeight;
            }

            set
            {
                if (_babyBirthWeight == value)
                {
                    return;
                }

                RaisePropertyChanging(BabyBirthWeightPropertyName);
                _babyBirthWeight = value;
                RaisePropertyChanged(BabyBirthWeightPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="BabyBirthHeadCircumference" /> property's name.
        /// </summary>
        public const string BabyBirthHeadCircumferencePropertyName = "BabyBirthHeadCircumference";

        private double? _babyBirthHeadCircumference = null;

        /// <summary>
        /// Sets and gets the BabyBirthHeadCircumference property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public double? BabyBirthHeadCircumference
        {
            get
            {
                return _babyBirthHeadCircumference;
            }

            set
            {
                if (_babyBirthHeadCircumference == value)
                {
                    return;
                }

                RaisePropertyChanging(BabyBirthHeadCircumferencePropertyName);
                _babyBirthHeadCircumference = value;
                RaisePropertyChanged(BabyBirthHeadCircumferencePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="Apgar" /> property's name.
        /// </summary>
        public const string ApgarPropertyName = "Apgar";

        private double? _apgar = null;

        /// <summary>
        /// Sets and gets the Apgar property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public double? Apgar
        {
            get
            {
                return _apgar;
            }

            set
            {
                if (_apgar == value)
                {
                    return;
                }

                RaisePropertyChanging(ApgarPropertyName);
                _apgar = value;
                RaisePropertyChanged(ApgarPropertyName);
            }
        }

        private RelayCommand<PatientViewModel> _updatePatientDataCommand;

        /// <summary>
        /// Gets the UpdatePatientDataCommand.
        /// </summary>
        public RelayCommand<PatientViewModel> UpdatePatientDataCommand
        {
            get
            {
                return _updatePatientDataCommand
                    ?? (_updatePatientDataCommand = new RelayCommand<PatientViewModel>(
                                          p =>
                                          {
                                              // Send UpdatePatientDataMessage to CreatePatientViewModel.
                                              RequestGotoPage(new CreatePatientPage());
                                              Messenger.Default.Send<PatientViewModel>(p, UpdatePatientDataMessageToken);
                                          }));
            }
        }

        /// <summary>
        /// Calcuate the mother BMI based on current MotherHeight & MotherWeight.
        /// </summary>
        private void CalcuateMotherBMI()
        {
            if (MotherHeight.HasValue && MotherWeight.HasValue)
            {
                MotherBMI = GeneralUtility.CalcuateBMI(MotherHeight.Value, MotherWeight.Value);
            }
        }
    }
}
